<script setup lang="ts">
import type { UploadProps } from 'ant-design-vue';

import { ref, watch } from 'vue';

import { Plus } from '@vben/icons';

import {
  Button,
  Form,
  InputNumber,
  message,
  Modal,
  Select,
  Table,
  Upload,
} from 'ant-design-vue';

// 定义API函数类型
interface GetSheetNamesFn {
  (formData: FormData): Promise<any>;
}

interface GetSheetHeadersFn {
  (params: { sheetName: string; startRow: number }): Promise<any>;
}

interface GetSheetDataPreviewFn {
  (params: {
    limit?: number;
    sheetName: string;
    startRow: number;
    fieldMappings?: string;
    excelHeaders?: string;
  }): Promise<any>;
}

interface ImportDataFn {
  (formData: FormData): Promise<any>;
}

/**
 * 定义组件属性
 * 用于接收父组件传入的API函数实现，实现了组件与数据源的解耦
 */
const props = defineProps<{
  getSheetDataPreviewApi: GetSheetDataPreviewFn;
  getSheetHeadersApi: GetSheetHeadersFn;
  // API函数，作为必需的props传入
  getSheetNamesApi: GetSheetNamesFn;
  importDataApi: ImportDataFn;
  systemFields?: Array<{
    label: string;
    value: string;
  }>;
}>();

/**
 * 定义组件可以发射的事件
 * 用于向父组件通信，通知导入成功或失败
 */
const emits = defineEmits<{
  'import-error': [error: any];
  'import-success': [data: any];
}>();

// 弹窗控制
const isModalVisible = ref(false);
const isImporting = ref(false);
const isLoading = ref(false);

// 文件相关
const file = ref<File | null>(null);
const fileName = ref('');
const fileContent = ref<string>('');

// 工作表相关
const sheetNames = ref<string[]>([]);
const selectedSheet = ref('');
const startRow = ref(1);

// 字段映射相关
const excelHeaders = ref<string[]>([]);
const fieldMappings = ref<string[]>([]);
const previewData = ref<any[]>([]);
const previewColumns = ref<any[]>([]);

// 系统字段配置（使用传入的字段或默认字段）
const systemFields = ref(
  props.systemFields || [
    { label: 'SKU', value: 'sku' },
    { label: '货品名称', value: 'product_name' },
    { label: '货品规格', value: 'specification' },
    { label: '状态', value: 'status' },
    { label: '类别', value: 'category' },
    { label: '单位', value: 'unit' },
    { label: '货品描述', value: 'description' },
    { label: '备注', value: 'remark' },
  ],
);

/**
 * 监听父组件传入的systemFields变化
 * 当父组件传入新的systemFields时，更新当前组件的systemFields
 */
watch(
  () => props.systemFields,
  (newFields) => {
    if (newFields) {
      systemFields.value = newFields;
    }
  },
  { immediate: true },
);

/**
 * 父组件调用的方法，显示导入弹窗
 */
const showImportModal = () => {
  isModalVisible.value = true;
};

/**
 * 关闭弹窗时重置
 */
const handleCancel = () => {
  resetImport();
};

/**
 * 处理文件上传前的验证
 * @param file 上传的文件
 * @returns 验证结果
 */
const handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {
  const isExcel =
    file.type === 'application/vnd.ms-excel' ||
    file.type ===
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
    file.name.endsWith('.xlsx') ||
    file.name.endsWith('.xls');

  if (!isExcel) {
    message.error('请上传Excel文件！');
    return Upload.LIST_IGNORE;
  }

  return false; // 阻止默认上传，使用自定义上传
};

/**
 * 处理文件选择变化
 * @param info 文件信息
 */
const handleFileChange = (info: any) => {
  // 更健壮地获取文件对象，处理不同版本的Ant Design Vue组件
  let selectedFile: File | null = null;

  if (info?.file?.originFileObj) {
    selectedFile = info.file.originFileObj;
  } else if (info?.file) {
    // 尝试直接使用file对象本身
    selectedFile = info.file as File;
  }

  if (selectedFile && selectedFile.name) {
    file.value = selectedFile;
    fileName.value = selectedFile.name;

    // 读取文件内容
    const reader = new FileReader();
    reader.onload = (e) => {
      fileContent.value = e.target?.result as string;
      // 上传文件并获取工作表名称
      uploadFileAndGetSheetNames();
    };
    reader.onerror = () => {
      message.error('读取文件失败');
    };
    reader.readAsDataURL(selectedFile);
  } else {
    message.error('请选择有效的Excel文件');
  }
};

/**
 * 上传文件并获取工作表名称
 */
const uploadFileAndGetSheetNames = async () => {
  if (!file.value) {
    return;
  }

  isLoading.value = true;
  try {
    const formData = new FormData();
    formData.append('file', file.value);
    // 直接使用传入的API函数
    const response = await props.getSheetNamesApi(formData);

    // 重置sheetNames
    sheetNames.value = [];

    // 检查响应结构并正确提取工作表名称
    if (response && typeof response === 'object') {
      // 处理API返回的标准格式 {code, message, sheet_names}
      if (response.code === 200) {
        // 优先检查response.sheet_names
        if (Array.isArray(response.sheet_names)) {
          sheetNames.value = response.sheet_names;
        }
        // 其次检查response.data.sheet_names
        else if (response.data && Array.isArray(response.data.sheet_names)) {
          sheetNames.value = response.data.sheet_names;
        }
        // 检查response.data是否为数组
        else if (Array.isArray(response.data)) {
          sheetNames.value = response.data;
        }
        // 检查response是否直接包含数组
        else if (Array.isArray(response)) {
          sheetNames.value = response;
        }
        // 如果找不到有效的工作表名称数组，显示错误
        else if (sheetNames.value.length === 0) {
          message.error('未能从响应中提取工作表名称');
        }
      }
      // 处理API返回错误码的情况
      else {
        message.error(`获取工作表名称失败: ${response.message || '未知错误'}`);
      }
    }
    // 处理响应不是对象的情况
    else {
      message.error('无效的响应类型');
    }

    if (sheetNames.value.length > 0) {
      selectedSheet.value = sheetNames.value[0] || '';
      handleSheetChange(selectedSheet.value);
    }
  } catch (error) {
    // 特殊处理：如果error对象包含code=200，表示实际上是成功响应
    if (typeof error === 'object' && error !== null) {
      const errorObj = error as Record<string, any>;
      if ('code' in errorObj && errorObj.code === 200) {
        if ('sheet_names' in errorObj && Array.isArray(errorObj.sheet_names)) {
          sheetNames.value = errorObj.sheet_names;
          if (sheetNames.value.length > 0) {
            selectedSheet.value = sheetNames.value[0] || '';
            handleSheetChange(selectedSheet.value);
          }
        }
      } else {
        message.error(
          `获取工作表名称失败: ${(error as Error)?.message}` || String(error),
        );
      }
    } else {
      message.error(`获取工作表名称失败: ${String(error)}`);
    }
  } finally {
    isLoading.value = false;
  }
};

/**
 * 处理工作表选择变化
 * @param value 选择的工作表名称
 */
const handleSheetChange = (value: any) => {
  if (value && typeof value === 'string') {
    selectedSheet.value = value;
    // 重置字段映射和预览数据
    excelHeaders.value = [];
    fieldMappings.value = [];
    previewData.value = [];
    previewColumns.value = [];
  }
};

/**
 * 处理开始行号变化
 * @param value 开始行号
 */
const handleStartRowChange = (value: any) => {
  // 确保值是有效的数字
  const numValue = Number(value);
  if (!isNaN(numValue) && numValue >= 1) {
    startRow.value = numValue;
  }
};

/**
 * 计算字符串相似度
 * @param str1 第一个字符串
 * @param str2 第二个字符串
 * @returns 相似度分数（0-1）
 */
const calculateSimilarity = (str1: string, str2: string): number => {
  if (!str1 || !str2) return 0;

  // 转小写并移除空白字符
  const s1 = str1.toLowerCase().replace(/\s+/g, '');
  const s2 = str2.toLowerCase().replace(/\s+/g, '');

  // 简单的包含关系匹配
  if (s1.includes(s2) || s2.includes(s1)) {
    return 1;
  }

  // 使用Jaccard相似度算法
  const set1 = new Set(s1.split(''));
  const set2 = new Set(s2.split(''));
  const intersection = new Set([...set1].filter((x) => set2.has(x)));
  const union = new Set([...set1, ...set2]);

  return intersection.size / union.size;
};

/**
 * 获取表头信息并自动映射字段
 */
const fetchSheetHeaders = async () => {
  if (!file.value || !selectedSheet.value || !startRow.value) return;

  isLoading.value = true;
  try {
    const params = {
      sheetName: selectedSheet.value,
      startRow: startRow.value,
    };

    // 直接使用传入的API函数
    const response = await props.getSheetHeadersApi(params);

    // 检查响应结构并正确提取表头信息
    if (Array.isArray(response)) {
      excelHeaders.value = response;
    } else if (response && typeof response === 'object') {
      // 处理可能的不同响应格式
      if (Array.isArray(response.headers)) {
        excelHeaders.value = response.headers;
      } else if (Array.isArray(response.data)) {
        excelHeaders.value = response.data;
      } else {
        message.error('表头格式错误');
        return;
      }
    } else {
      message.error('无效的响应类型');
      return;
    }

    // 初始化字段映射数组
    fieldMappings.value = new Array(excelHeaders.value.length).fill('');

    // 按标题名称自动配对字段
    let autoMappedCount = 0;
    excelHeaders.value.forEach((header, index) => {
      if (systemFields.value.length > 0) {
        // 寻找最匹配的系统字段
        let bestMatch: null | { similarity: number; value: string } = null;

        systemFields.value.forEach((field) => {
          const similarity = calculateSimilarity(header, field.label);
          if (!bestMatch || similarity > bestMatch.similarity) {
            bestMatch = { value: field.value, similarity };
          }
        });

        // 如果相似度足够高，则自动映射
        if (
          bestMatch &&
          (bestMatch as { similarity: number; value: string }).similarity > 0.5
        ) {
          fieldMappings.value[index] = (
            bestMatch as { similarity: number; value: string }
          ).value;
          autoMappedCount++;
        }
      }
    });

    // 如果有自动映射的字段，提示用户
    if (autoMappedCount > 0) {
      message.success(`已自动映射 ${autoMappedCount} 个字段，请检查确认`);
    }

    // 不自动获取数据预览，让用户在完成字段映射后手动获取
  } catch (error) {
    message.error(
      `解析表头失败: ${(error as Error)?.message}` || String(error),
    );
  } finally {
    isLoading.value = false;
  }
};

/**
 * 获取数据预览
 */
const fetchDataPreview = async () => {
  if (!file.value || !selectedSheet.value || !startRow.value) return;

  try {
    // 检查是否有映射的字段
    const hasMappedFields = fieldMappings.value.some((field) => field);
    if (!hasMappedFields) {
      message.warning('请至少映射一个字段');
      return;
    }

    const params = {
      sheetName: selectedSheet.value,
      startRow: startRow.value,
      limit: 5,
      fieldMappings: JSON.stringify(fieldMappings.value),
      excelHeaders: JSON.stringify(excelHeaders.value),
    };

    // 直接使用传入的API函数
    const response = await props.getSheetDataPreviewApi(params);

    // 检查响应结构并正确提取数据
    if (response && typeof response === 'object') {
      // 尝试多种可能的响应格式
      let rawPreviewData = [];
      if (Array.isArray(response.data)) {
        rawPreviewData = response.data;
      } else if (Array.isArray(response.preview_data)) {
        rawPreviewData = response.preview_data;
      } else {
        message.error('预览数据格式错误');
        return;
      }

      // 处理后端返回的数据格式 - 后端使用column_0格式的键名
      previewData.value = rawPreviewData.map((row: any) => {
        const mappedRow: any = {};
        Object.entries(row).forEach(([key, value]) => {
          // 检查键名是否为column_0格式
          if (key.startsWith('column_')) {
            const index = parseInt(key.replace('column_', ''));
            if (
              !isNaN(index) &&
              index < excelHeaders.value.length &&
              excelHeaders.value[index] !== undefined
            ) {
              // 使用原始表头作为键名
              mappedRow[excelHeaders.value[index]] = value;
            }
          } else {
            // 保留其他键名
            mappedRow[key] = value;
          }
        });
        return mappedRow;
      });

      // 使用已有的excelHeaders构建预览列
      // 考虑字段映射，显示映射关系
      previewColumns.value = excelHeaders.value
        .map((header: string, index: number) => {
          const mappedField = fieldMappings.value[index];
          const systemFieldObj = systemFields.value.find(
            (f) => f.value === mappedField,
          );
          const displayTitle = mappedField
            ? `${header} → ${systemFieldObj?.label || mappedField}`
            : header;

          return {
            title: displayTitle,
            dataIndex: header, // 使用原始表头作为dataIndex
            key: header,
            ellipsis: true, // 超出显示省略号
          };
        })
        .filter(
          (col) =>
            fieldMappings.value[excelHeaders.value.indexOf(col.dataIndex)],
        ); // 只显示已映射的列
    } else {
      message.error('无效的响应类型');
    }
  } catch (error) {
    // 特殊处理：如果error对象包含code=200，表示实际上是成功响应
    if (typeof error === 'object' && error !== null) {
      const errorObj = error as Record<string, any>;
      if ('code' in errorObj && errorObj.code === 200) {
        if (
          'preview_data' in errorObj &&
          Array.isArray(errorObj.preview_data)
        ) {
          // 处理后端返回的数据格式 - 后端使用column_0格式的键名
          previewData.value = errorObj.preview_data.map((row: any) => {
            const mappedRow: any = {};
            Object.entries(row).forEach(([key, value]) => {
              // 检查键名是否为column_0格式
              if (key.startsWith('column_')) {
                const index = parseInt(key.replace('column_', ''));
                if (
                  !isNaN(index) &&
                  index < excelHeaders.value.length &&
                  excelHeaders.value[index] !== undefined
                ) {
                  // 使用原始表头作为键名
                  mappedRow[excelHeaders.value[index]] = value;
                }
              } else {
                // 保留其他键名
                mappedRow[key] = value;
              }
            });
            return mappedRow;
          });

          // 使用已有的excelHeaders构建预览列
          previewColumns.value = excelHeaders.value
            .map((header: string, index: number) => {
              const mappedField = fieldMappings.value[index];
              const systemFieldObj = systemFields.value.find(
                (f) => f.value === mappedField,
              );
              const displayTitle = mappedField
                ? `${header} → ${systemFieldObj?.label || mappedField}`
                : header;

              return {
                title: displayTitle,
                dataIndex: header,
                key: header,
                ellipsis: true,
              };
            })
            .filter(
              (col) =>
                fieldMappings.value[excelHeaders.value.indexOf(col.dataIndex)],
            );
        }
      } else {
        message.error(
          `获取数据预览失败: ${(error as Error)?.message}` || String(error),
        );
      }
    } else {
      message.error(`获取数据预览失败: ${String(error)}`);
    }
  }
};

/**
 * 执行导入
 */
const doImport = async () => {
  if (!file.value || !selectedSheet.value || !startRow.value) {
    message.warning('请选择文件并配置导入参数');
    return;
  }

  // 检查是否有映射的字段
  const hasMappedFields = fieldMappings.value.some((field) => field);
  if (!hasMappedFields) {
    message.warning('请至少映射一个字段');
    return;
  }

  isImporting.value = true;
  try {
    const formData = new FormData();
    formData.append('file', file.value);
    formData.append('sheetName', selectedSheet.value);
    formData.append('startRow', startRow.value.toString());
    formData.append('fieldMappings', JSON.stringify(fieldMappings.value));
    formData.append('excelHeaders', JSON.stringify(excelHeaders.value));

    // 直接使用传入的API函数
    const response = await props.importDataApi(formData);

    // 处理导入成功响应
    let importResult = response;
    if (response && typeof response === 'object') {
      // 提取可能的嵌套数据
      if (response.data) {
        importResult = response.data;
      } else if (response.success_count !== undefined) {
        // 如果已经是期望的格式，直接使用
        importResult = response;
      }
    }

    message.success('导入成功');
    isModalVisible.value = false;
    resetImport();
    // 通知父组件导入成功
    emits('import-success', importResult);
  } catch (error) {
    message.error(`导入失败: ${(error as Error)?.message}` || String(error));
    // 通知父组件导入失败
    emits('import-error', error);
  } finally {
    isImporting.value = false;
  }
};

/**
 * 清除文件
 */
const clearFile = () => {
  file.value = null;
  fileName.value = '';
  fileContent.value = '';
  sheetNames.value = [];
  selectedSheet.value = '';
  startRow.value = 1;
  excelHeaders.value = [];
  fieldMappings.value = [];
  previewData.value = [];
  previewColumns.value = [];
};

/**
 * 重置导入设置
 */
const resetImport = () => {
  clearFile();
  isModalVisible.value = false;
};

// 提供给父组件的方法
defineExpose({
  showImportModal,
});
</script>

<template>
  <div class="data-import-container">
    <!-- 数据导入弹窗 -->
    <Modal
      v-model:open="isModalVisible"
      title="数据导入"
      ok-text="执行导入"
      cancel-text="取消"
      @ok="doImport"
      :confirm-loading="isImporting"
      @cancel="handleCancel"
      width="1200px"
    >
      <Form layout="vertical">
        <!-- 文件上传 -->
        <Upload
          :before-upload="handleBeforeUpload"
          :show-upload-list="false"
          accept=".xlsx,.xls"
          @change="handleFileChange"
        >
          <Button type="primary">
            <Plus class="size-5" /> 选择Excel文件
          </Button>
        </Upload>

        <div v-if="fileName" class="file-name">
          已选择文件: {{ fileName }}
          <Button type="text" @click="clearFile">清除</Button>
        </div>

        <!-- 表名选择 -->
        <Form.Item label="表名" v-if="sheetNames.length > 0">
          <Select
            v-model:value="selectedSheet"
            style="width: 200px"
            @change="handleSheetChange"
            placeholder="请选择要导入的工作表"
          >
            <Select.Option
              v-for="sheet in sheetNames"
              :key="sheet"
              :value="sheet"
            >
              {{ sheet }}
            </Select.Option>
          </Select>
        </Form.Item>

        <!-- 开始行号设置 -->
        <Form.Item label="开始行号" v-if="selectedSheet">
          <InputNumber
            v-model:value="startRow"
            :min="1"
            style="width: 120px"
            @change="handleStartRowChange"
          />
          <span class="start-row-tip">（表头所在行）</span>
        </Form.Item>

        <!-- 获取表头按钮 -->
        <Button
          type="primary"
          @click="fetchSheetHeaders"
          v-if="selectedSheet && startRow"
          :loading="isLoading"
          :disabled="isLoading"
          style="margin-bottom: 16px"
        >
          解析表头
        </Button>

        <!-- 字段映射区域 -->
        <div class="field-mapping" v-if="excelHeaders.length > 0">
          <h4>字段映射设置</h4>
          <div class="mapping-table">
            <div class="mapping-header">
              <div class="header-item">Excel列</div>
              <div class="header-item">系统字段</div>
            </div>
            <div
              class="mapping-row"
              v-for="(header, index) in excelHeaders"
              :key="index"
            >
              <div class="mapping-cell">{{ header }}</div>
              <div class="mapping-cell">
                <Select
                  v-model:value="fieldMappings[index]"
                  placeholder="选择对应字段"
                  :options="systemFields"
                  allow-clear
                  style="width: 100%"
                />
              </div>
            </div>
          </div>
          <Button
            type="primary"
            @click="fetchDataPreview"
            :loading="isLoading"
            :disabled="isLoading"
            style="margin-top: 16px; margin-bottom: 16px"
          >
            获取数据预览
          </Button>
        </div>

        <!-- 数据预览区域 -->
        <div class="data-preview" v-if="previewData.length > 0">
          <h4>数据预览 (前5行)</h4>
          <Table
            :columns="previewColumns"
            :data-source="previewData"
            :pagination="false"
            size="small"
          />
        </div>
      </Form>
    </Modal>
  </div>
</template>

<style scoped>
.data-import-container {
  margin-bottom: 16px;
}

.file-name {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-top: 16px;
}

.field-mapping {
  margin-top: 16px;
}

.mapping-table {
  margin-top: 8px;
}

.mapping-header {
  display: flex;
  padding: 8px;
  font-weight: bold;
  border-radius: 4px 4px 0 0;
}

.header-item {
  width: 200px;
}

.mapping-row {
  display: flex;
  padding: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.mapping-cell {
  width: 200px;
}

.data-preview {
  margin-top: 16px;
}

.start-row-tip {
  margin-left: 8px;
  color: #8c8c8c;
}
</style>
